package dper.study.codes.concurrent.service;

import dper.study.codes.concurrent.api.ConcurrentExampleAPI;
import dper.study.codes.concurrent.model.ParellelResult;
import dper.study.codes.concurrent.model.ParellelType;
import dper.study.codes.concurrent.utils.ParellelUtils;
import dper.study.codes.concurrent.worker.DateFormatWorker;
import dper.study.codes.concurrent.worker.TimeSleepWorker;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * Created by leichen on 2017/3/17.
 */
@Service
public class ConcurrentExampleService implements ConcurrentExampleAPI{

    private Logger logger = Logger.getLogger(ConcurrentExampleService.class) ;


    public int timeConsumptionMultiTask() {
        List<Future<ParellelResult>>  futureList =  new ArrayList<Future<ParellelResult>>( ) ;
        long start=System.currentTimeMillis();
        futureList.add(ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker())) ;
        futureList.add(ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker())) ;
        futureList.add(ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker())) ;
        int ret = 1 ;

        for (Future<ParellelResult> future:futureList){
            try {
                ParellelResult res = future.get() ;
                logger.info(res.isSuccess() + "\t" + res.getResult() + "\t" +future.isDone()) ;
                ret = ret & (res.isSuccess() ? 1 : 0 );
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        long end=System.currentTimeMillis();
        logger.info("time consume " + (end - start) + "millis .All workers run " + (ret==1 ? "normal" : "unnormal") );
        return ret ;
    }

    public int displayCountDownLatchUsage() {
        CountDownLatch countDownLatch = new CountDownLatch(3) ;
        ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker(countDownLatch)) ;
        ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker(countDownLatch)) ;
        ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker(countDownLatch)) ;

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("countDownLatch await until all workers job done !");
        return (int)countDownLatch.getCount();
    }

    public int displayCyclicBarrierUsage() {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
            public void run() {
                logger.info("cyclicBarrier workers done ! congratulation");
            }
        }) ;
        ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker(cyclicBarrier)) ;
        ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker(cyclicBarrier)) ;
        ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker(cyclicBarrier)) ;
        return 0;
    }

    public int displayThreadLocalUsage() {
        List<Future<ParellelResult>>  futureList =  new ArrayList<Future<ParellelResult>>( ) ;
        long start=System.currentTimeMillis();
        futureList.add(ParellelUtils.threadPoolTemplate.submit(new DateFormatWorker())) ;
        futureList.add(ParellelUtils.threadPoolTemplate.submit(new DateFormatWorker())) ;
        futureList.add(ParellelUtils.threadPoolTemplate.submit(new DateFormatWorker())) ;
        futureList.add(ParellelUtils.threadPoolTemplate.submit(new TimeSleepWorker())) ;
        for (Future<ParellelResult> future:futureList){
            try {
                ParellelResult res = future.get() ;
                if(res.getParellelType()== ParellelType.PT_DATE_FORMAT)
                    logger.info("PT_DATE_FORMAT\t"+res.isSuccess() + "\t" + res.getResult() + "\t" +future.isDone()) ;
                if(res.getParellelType()== ParellelType.PT_TIME_SLEEP)
                    logger.info("PT_TIME_SLEEP\t"+res.isSuccess() + "\t" + res.getResult() + "\t" +future.isDone()) ;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        long end=System.currentTimeMillis();
        logger.info("time consume " + (end - start) + "millis ") ;
        return 0;
    }

    public int displaySimpleThreadFutureFutureTaskCallableRunnableUsage() {
        TimeSleepWorker timeSleepWorker1 = new TimeSleepWorker() ;
        FutureTask<ParellelResult> futureTask1 = new FutureTask<ParellelResult>(timeSleepWorker1) ;
        Thread thread1 = new Thread(futureTask1) ;
        thread1.start();
        try {
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 0;
    }

}
